package com.th.supcom.pds.impl.service.adapter;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.carefx.fc.framework.web.gwt.util.FcUtils;
import net.carefx.framework.exception.BusinessException;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.th.supcom.dms.pharm.storage.domain.pojo.PhamDocuDetail;
import com.th.supcom.dms.pharm.storage.domain.pojo.PhamDocuHead;
import com.th.supcom.dms.pharm.storage.domain.pojo.PhamStockOnwayTable;
import com.th.supcom.dms.pharm.storage.service.PhamStockOutService;
import com.th.supcom.pds.domain.pojo.PdsSupplyPro;
import com.th.supcom.pds.domain.vo.InpPhamApplyDetailVO;
import com.th.supcom.pds.domain.vo.InpPhamDispenseDetailVO;
import com.th.supcom.pds.domain.vo.PdsSupplyDetailVO;
import com.th.supcom.pds.domain.vo.PdsSupplyResultSet;
import com.th.supcom.pds.domain.vo.PdsSupplyVO;
import com.th.supcom.pds.impl.common.PdsConstants;
import com.th.supcom.pds.impl.common.enums.InpDispenseIndicator;
import com.th.supcom.pds.impl.common.enums.PhamIOType;
import com.th.supcom.pds.impl.common.enums.PhamIoSort;
import com.th.supcom.pds.impl.common.utils.ExceptionThrowHelper;
import com.th.supcom.pds.impl.service.internal.phamapply.PhamDispenseConvertUtils;
import com.th.supcom.pds.internal.api.PdsSupplyProService;
import com.th.supcom.pds.medicare.api.AdapterDrugManagerService;

/**
 * 调用药品进销存系统接口服务类
 * 
 * @author 杨冲
 */
public class AdapterDrugManagerServiceImpl implements AdapterDrugManagerService
{
    /** 日志记录器. */
    private static final Logger s_LOGGER = LoggerFactory.getLogger (AdapterDrugManagerServiceImpl.class);
    private PhamStockOutService m_phamStockOutService;
    private PdsSupplyProService m_pdsSupplyProService;

    public void setPhamStockOutService (PhamStockOutService phamStockOutService)
    {

        m_phamStockOutService = phamStockOutService;
    }

    public void setPdsSupplyProService (PdsSupplyProService pdsSupplyProService)
    {

        m_pdsSupplyProService = pdsSupplyProService;
    }

    /**
     * 将PDS中的明细表对象列表转换成DMS的PhamDocuDetail对象列表
     * 
     * @return
     */
    private List <PhamDocuDetail> convertPdsToDMSList (List <PdsSupplyDetailVO> pdsPrescDetailCombines, String phamIoType)
    {
        if (pdsPrescDetailCombines.isEmpty ())
        {
            return null;
        }

        List <PhamDocuDetail> phamDocuDetails = new ArrayList <PhamDocuDetail> ();
        for (PdsSupplyDetailVO pdsPrescDetailCombine : pdsPrescDetailCombines)
        {
            phamDocuDetails.add (convertPdsToDMS (pdsPrescDetailCombine, phamIoType));
        }
        return phamDocuDetails;
    }

    /**
     * 将PDS中的明细表对象转换成DMS的PhamDocuDetail对象
     * 
     * @param pdsPhamDocuDetail 入库药品信息
     * @param phamIoType 入库类型
     * @return
     */
    private PhamDocuDetail convertPdsToDMS (PdsSupplyDetailVO pdsPrescDetailCombine, String phamIoType)
    {
        if (null == pdsPrescDetailCombine)
        {
            return null;
        }
        PhamDocuDetail phamDocuDetail = new PhamDocuDetail ();
        phamDocuDetail.setUnit (pdsPrescDetailCombine.getPackageUnit ());
        phamDocuDetail.setQuantity (pdsPrescDetailCombine.getUnitQty ());
        phamDocuDetail.setFactor (pdsPrescDetailCombine.getFactor ());
        if (PhamIOType.PhamIn.getEnumCode ().equals (phamIoType))
        {
            phamDocuDetail.setPhamBatchNumber (pdsPrescDetailCombine.getPhamBatchNumber ());
            phamDocuDetail.setReceiptDate (pdsPrescDetailCombine.getReceiptDate ());
        }
        phamDocuDetail.setPhamStdCode (pdsPrescDetailCombine.getPhamStdCode ());
        return phamDocuDetail;
    }

    @Override
    public void drugStockOut (List <PdsSupplyDetailVO> pdsPrescDetailCombines, Map <String, Object> map)
    {
        s_LOGGER.info ("调用drugStockOut (List<PdsSupplyDetailVO> = 【{}】", new Object[]
        { pdsPrescDetailCombines });
        try
        {
            PhamDocuHead phamDocuHead = convertPdsToPhamDocuHead (pdsPrescDetailCombines, map, PhamIOType.PhamOut.getEnumCode ());
            String exNO = m_phamStockOutService.takeDrugStockOut (phamDocuHead);
            updatePdsSupplyVO (pdsPrescDetailCombines, exNO);
        }
        catch (Exception e)
        {
            s_LOGGER.error (e.getMessage (), e);
            throw new BusinessException ("药品出库出现异常" + PdsConstants.DEFALUT_HTML_WRAP + e.getMessage (), e);
        }

    }

    /**
     * 更新库存单据号
     * 
     * @param pdsPrescDetailCombines
     * @param exNo
     */
    private void updatePdsSupplyVO (List <PdsSupplyDetailVO> pdsPrescDetailCombines, String exNo)
    {
        for (PdsSupplyDetailVO pdsPrescDetailCombine : pdsPrescDetailCombines)
        {
            PdsSupplyPro pdsSupplyPro = new PdsSupplyPro ();
            pdsSupplyPro.setId (pdsPrescDetailCombine.getProId ());
            pdsSupplyPro.setExNo (exNo);
            // 更新供药过程
            m_pdsSupplyProService.modifyPdsSupplyProByExample (pdsSupplyPro);
        }

    }

    /**
     * 将PDS中的明细表对象转换成DMS的PhamDocuHead对象</br> deptCode 当前药房ID</br> phamIoSign
     * 1表示是入库流水，0表示是出库流水（退药入库：1；领药出库：0，必须按这个填写）</br> deliverer 库存的库房ID</br>
     * phamIoDate 退药的时间 </br> empIdOperator 操作人ID </br> phamIoSort 入库分类编码
     * （退药入库：1001；领药出库：2007，必须按这个填写）</br> phamIoSortName 入库分类名 </br>
     * phamDocuDetailList 要入库的药品集合，其中必要的数据： 字段 解释</br> phamStdCode 药品ID</br>
     * phamBatchNumber批次号(退药入库：不填会自动给***，领药出库：不用填，会自动找最近的批次和有效期)</br>
     * receiptDate 有效期（退药入库：不填会自动给9000年1月1日，领药出库：不用填，会自动找最近的批次和有效期）</br>
     * quantity 出入库数量 </br> unit 出入库的单位ID</br> baseQuantity 出入库基本数量（最小数量）</br>
     * baseUnit 基本单位ID</br> factor入库单位和基本单位的换算系数（一定大于等于1）
     * 
     * @param pdsPrescDetailCombines
     * @return PhamDocuHead
     */
    private PhamDocuHead convertPdsToPhamDocuHead (List <PdsSupplyDetailVO> pdsPrescDetailCombines, Map <String, Object> map, String phamIoType)
    {
        if (pdsPrescDetailCombines.isEmpty ())
        {
            return null;
        }
        PhamDocuHead docuHead = new PhamDocuHead ();
        if (PhamIOType.PhamIn.getEnumCode ().equals (phamIoType))
        {
            docuHead.setPhamIoSign (PhamIOType.PhamIn.getEnumCode ());
            docuHead.setDeliverer ((String) map.get ("patientId"));// 收货方 患者ID
            docuHead.setReceiver ((String) map.get ("dispensaryCode"));// 发货方
                                                                       // 执行科室
            docuHead.setPhamIoSort (PhamIoSort.PhamIn.getEnumCode ());
            docuHead.setPhamIoSortName (PhamIoSort.PhamIn.getEnumName ());
        }
        else
        {
            docuHead.setPhamIoSign (PhamIOType.PhamOut.getEnumCode ());
            docuHead.setDeliverer ((String) map.get ("dispensaryCode"));// 收货方
                                                                        // 患者id
            docuHead.setReceiver ((String) map.get ("patientId"));// 发货方
            docuHead.setPhamIoSort (PhamIoSort.PhamOut.getEnumCode ());
            docuHead.setPhamIoSortName (PhamIoSort.PhamOut.getEnumName ());
        }
        docuHead.setDeptCode ((String) map.get ("dispensaryCode"));
        docuHead.setPhamIoDate (FcUtils.getCurrentServerDateTimeForServer ());
        docuHead.setEmpIdOperator ((String) map.get ("operator"));
        List <PhamDocuDetail> phamDocuDetails = convertPdsToDMSList (pdsPrescDetailCombines, phamIoType);
        docuHead.setPhamDocuDetailList (phamDocuDetails);
        return docuHead;
    }

    @Override
    public String outpDrugStockIn (PdsSupplyResultSet pdsSupplyResultSet)
    {
        s_LOGGER.info ("调用drugStockIn (List<PdsPrescDetailCombine> = 【{}】", new Object[]
        { pdsSupplyResultSet });
        try
        {
            PhamDocuHead phamDocuHead = convertDrugReturn (pdsSupplyResultSet);
            return m_phamStockOutService.drugReturnStockIn (phamDocuHead);
        }
        catch (Exception e)
        {
            s_LOGGER.error (e.getMessage (), e);
            throw new BusinessException ("药品入库出现异常" + PdsConstants.DEFALUT_HTML_WRAP + e.getMessage (), e);
        }
    }

    /**
     * 转换退药数据
     * 
     * @param pdsSupplyResultSet
     * @return
     */
    private PhamDocuHead convertDrugReturn (PdsSupplyResultSet pdsSupplyResultSet)
    {
        if (pdsSupplyResultSet == null)
        {
            return null;
        }
        PhamDocuHead docuHead = new PhamDocuHead ();
        PdsSupplyVO pdsSupplyVO = pdsSupplyResultSet.getPdsSupplyVO ();
        docuHead.setPhamIoSign (PhamIOType.PhamIn.getEnumCode ());
        docuHead.setDeliverer (pdsSupplyVO.getOrgIdExec ());// 收货方 患者ID
        docuHead.setReceiver (pdsSupplyVO.getPatientId ());// 发货方 执行科室
        docuHead.setPhamIoSort (PhamIoSort.PhamIn.getEnumCode ());
        docuHead.setPhamIoSortName (PhamIoSort.PhamIn.getEnumName ());
        docuHead.setDeptCode (pdsSupplyVO.getOrgIdExec ());
        docuHead.setPhamIoDate (FcUtils.getCurrentServerDateTimeForServer ());
        docuHead.setEmpIdOperator (pdsSupplyResultSet.getOperatorCode ());
        List <PdsSupplyDetailVO> supplyDetailVOs = pdsSupplyResultSet.getPdsSupplyDetailVOs ();
        for (PdsSupplyDetailVO pdsSupplyDetailVO : supplyDetailVOs)
        {
            pdsSupplyDetailVO.setUnitQty (pdsSupplyDetailVO.getReturnQty ());
            Double baseQty = pdsSupplyDetailVO.getReturnQty () * pdsSupplyDetailVO.getFactor ();
            pdsSupplyDetailVO.setQtySum (baseQty);
        }
        List <PhamDocuDetail> phamDocuDetails = convertPdsToDMSList (pdsSupplyResultSet.getPdsSupplyDetailVOs (), PhamIOType.PhamIn.getEnumCode ());
        docuHead.setPhamDocuDetailList (phamDocuDetails);
        return docuHead;
    }

    @Override
    public void sendStockOutInfo (List <PdsSupplyDetailVO> pdsPrescDetailCombines)
    {
        s_LOGGER.info ("调用sendStockOutInfo (List <PdsPrescDetailCombine> pdsPrescDetailCombines = 【{}】", new Object[]
        { pdsPrescDetailCombines });
        // TODO发送出库信息
        try
        {
            return;
        }
        catch (Exception e)
        {
            throw new BusinessException (e.getLocalizedMessage (), e);
        }
    }

    /**
     * 住院 药房退药入库
     * 
     * @param InpPhamApplyDetailVOs
     * @param operator 操作人
     * @param phamIoSortCode 退药方式
     * @return
     */
    @Override
    public String inpDrugStockIn (List <InpPhamApplyDetailVO> inpPhamApplyDetailVOs, Map <String, Object> infoMap, String phamIoSortCode)
    {
        s_LOGGER.info ("调用drugStockOut (List<PdsPrescDetailCombine> = 【{}】", new Object[]
        { inpPhamApplyDetailVOs });
        ExceptionThrowHelper.throwIllegalArgumentException (CollectionUtils.isEmpty (inpPhamApplyDetailVOs), "调用退药接口时,传入参数为空");
        try
        {
            PhamDocuHead phamDocuHead = convertInpApplyDetailToPhamDocuHead (inpPhamApplyDetailVOs, infoMap, phamIoSortCode);
            String exNo = m_phamStockOutService.drugReturnStockIn (phamDocuHead);
            return exNo;
        }
        catch (Exception e)
        {
            s_LOGGER.error (e.getMessage (), e);
            throw new BusinessException ("药品入库出现异常" + PdsConstants.DEFALUT_HTML_WRAP, e);
        }

    }

    private PhamDocuHead convertInpApplyDetailToPhamDocuHead (List <InpPhamApplyDetailVO> inpPhamApplyDetailVOs, Map <String, Object> infoMap, String phamIoSortCode)
    {
        InpPhamApplyDetailVO inpPhamApplyDetailVO = inpPhamApplyDetailVOs.get (0);
        PhamDocuHead phamDocuHead = new PhamDocuHead ();
        phamDocuHead.setDeptCode (inpPhamApplyDetailVO.getExecDispensary ());
        // 判断是出库还是入库
        if (inpPhamApplyDetailVO.getApplyAmount () < 0)
        {
            phamDocuHead.setPhamIoSign (PhamIOType.PhamIn.getEnumCode ());
            phamDocuHead.setDeliverer (inpPhamApplyDetailVO.getApplyDispensary ());
            phamDocuHead.setReceiver (inpPhamApplyDetailVO.getPatientId ());
            phamDocuHead.setDeliverOrg ((String) infoMap.get ("nurseUnit"));
        }
        else
        {
            phamDocuHead.setPhamIoSign (PhamIOType.PhamOut.getEnumCode ());
            phamDocuHead.setDeliverer (inpPhamApplyDetailVO.getPaiVisitId ().toString ());
            phamDocuHead.setReceiver (inpPhamApplyDetailVO.getApplyDispensary ());
        }
        phamDocuHead.setPhamIoDate (FcUtils.getCurrentServerDateTimeForServer ());
        phamDocuHead.setEmpIdOperator ((String) infoMap.get ("operator"));
        phamDocuHead.setPhamIoSort (phamIoSortCode);
        phamDocuHead.setPhamIoSortName (PhamIoSort.getEnumByCode (phamIoSortCode).getEnumName ());
        List <PhamDocuDetail> phamDocuDetails = new ArrayList <PhamDocuDetail> ();
        for (InpPhamApplyDetailVO vo : inpPhamApplyDetailVOs)
        {
            if (null == vo)
            {
                return null;
            }
            PhamDocuDetail phamDocuDetail = new PhamDocuDetail ();
            phamDocuDetail.setBaseUnit (vo.getApplyUnit ());
            phamDocuDetail.setUnit (vo.getApplyUnit ());
            phamDocuDetail.setBaseQuantity (Math.abs (vo.getApplyAmount ().doubleValue ()));
            phamDocuDetail.setQuantity (Math.abs (vo.getApplyAmount ().doubleValue ()));
            phamDocuDetail.setFactor (1.0);
            phamDocuDetail.setPhamBatchNumber (vo.getPhamBatchNo ());
            phamDocuDetail.setReceiptDate (vo.getExpiryDate ());
            phamDocuDetail.setPhamStdCode (vo.getPhamStdCode ());
            phamDocuDetails.add (phamDocuDetail);
        }
        phamDocuHead.setPhamDocuDetailList (phamDocuDetails);
        return phamDocuHead;

    }

    @Override
    public List <InpPhamDispenseDetailVO> phamApplyStockOp (List <InpPhamDispenseDetailVO> detailList)
    {
        s_LOGGER.debug ("调用药品批量出库异常,参数:detailList{}", new Object[]
        { detailList });
        List <PhamDocuHead> docuHeads = new ArrayList <PhamDocuHead> ();
        // 将执行明细按照患者住院流水号分组
        Map <Long, List <InpPhamDispenseDetailVO>> dispenseDetailMap = PhamDispenseConvertUtils.convertListToMapByPaivisitID (detailList);
        Set <Map.Entry <Long, List <InpPhamDispenseDetailVO>>> set = dispenseDetailMap.entrySet ();
        for (Iterator <Map.Entry <Long, List <InpPhamDispenseDetailVO>>> it = set.iterator (); it.hasNext ();)
        {
            Map.Entry <Long, List <InpPhamDispenseDetailVO>> entry = (Map.Entry <Long, List <InpPhamDispenseDetailVO>>) it.next ();
            List <InpPhamDispenseDetailVO> patDetailList = entry.getValue ();
            // 没有患者执行明细
            if (CollectionUtils.isEmpty (patDetailList))
            {
                continue;
            }
            // 患者药品出入库主记录
            PhamDocuHead docuHead = new PhamDocuHead ();
            docuHead.setDeptCode (patDetailList.get (0).getPerformDispensary ());
            docuHead.setPhamIoSign (PhamIOType.PhamOut.getEnumCode ());
            docuHead.setReceiver (patDetailList.get (0).getPerformDispensary ());
            docuHead.setDeliverer (patDetailList.get (0).getPaiVisitId () + "");
            docuHead.setPhamIoDate (FcUtils.getCurrentServerDateTimeForServer ());
            docuHead.setEmpIdOperator (patDetailList.get (0).getDispenseBy ());
            docuHead.setPhamIoSort (PhamIoSort.InpDispense.getEnumCode ());
            docuHead.setPhamIoSortName (PhamIoSort.InpDispense.getEnumName ());
            docuHead.setPdsApplyId (patDetailList.get (0).getApplyNo ());
            docuHead.setDeliverOrg (patDetailList.get (0).getNurseUnit ());
            // 药品出入库明细
            List <PhamDocuDetail> docuDetailList = new ArrayList <PhamDocuDetail> ();
            for (InpPhamDispenseDetailVO inpPhamDispenseDetailVO : patDetailList)
            {
                PhamDocuDetail docuDetail = new PhamDocuDetail ();
                docuDetail.setPhamStdCode (inpPhamDispenseDetailVO.getPhamStdCode ());
                docuDetail.setQuantity (Double.parseDouble (inpPhamDispenseDetailVO.getApplyAmount () + ""));
                docuDetail.setUnit (inpPhamDispenseDetailVO.getDispenseUnit ());
                docuDetail.setFactor (Double.parseDouble (inpPhamDispenseDetailVO.getFactor () + ""));
                docuDetailList.add (docuDetail);
            }
            docuHead.setPhamDocuDetailList (docuDetailList);
            docuHeads.add (docuHead);
        }
        Map <String, Map <String, String>> docuResult;
        try
        {
            docuResult = m_phamStockOutService.drugDispense (docuHeads);
        }
        catch (Exception e)
        {
            s_LOGGER.error ("调用药品批量出库异常:" + e.getLocalizedMessage (), e);
            throw new BusinessException ("调用药品批量出库异常:" + e.getLocalizedMessage (), e);
        }
        for (Iterator <Map.Entry <Long, List <InpPhamDispenseDetailVO>>> it = set.iterator (); it.hasNext ();)
        {
            Map.Entry <Long, List <InpPhamDispenseDetailVO>> entry = (Map.Entry <Long, List <InpPhamDispenseDetailVO>>) it.next ();
            List <InpPhamDispenseDetailVO> patDetailList = entry.getValue ();
            // 没有患者执行明细
            if (CollectionUtils.isEmpty (patDetailList))
            {
                continue;
            }
            Map <String, String> patPhamDocu = docuResult.get (patDetailList.get (0).getPaiVisitId () + "");
            for (InpPhamDispenseDetailVO inpPhamDispenseDetailVO : patDetailList)
            {
                String stockNo = patPhamDocu.get (inpPhamDispenseDetailVO.getPhamStdCode ());
                inpPhamDispenseDetailVO.setStockNo (stockNo);
                inpPhamDispenseDetailVO.setDispenseIndicator (InpDispenseIndicator.Sorted.getEnumCode ());
            }
        }
        return detailList;
    }

    @Override
    public void offsetDetailStockOp (List <InpPhamApplyDetailVO> applyDetailList)
    {
        s_LOGGER.debug ("调用药品冲抵退药入库，参数：applyDetailList{}", new Object[]
        { applyDetailList });
        List <PhamStockOnwayTable> bufferList = new ArrayList <PhamStockOnwayTable> ();
        for (InpPhamApplyDetailVO inpPhamApplyDetailVO : applyDetailList)
        {
            if (inpPhamApplyDetailVO.getOffsetSum () != null)
            {
                PhamStockOnwayTable buffer = new PhamStockOnwayTable ();
                buffer.setDeliverOrg (inpPhamApplyDetailVO.getNurseUnit ());
                buffer.setPhamStdCode (inpPhamApplyDetailVO.getPhamStdCode ());
                buffer.setQuantity (Long.valueOf (inpPhamApplyDetailVO.getOffsetSum () + ""));
                bufferList.add (buffer);
            }
        }
        try
        {
            if (!CollectionUtils.isEmpty (bufferList))
            {
                m_phamStockOutService.offsetStockIn (bufferList);
            }

        }
        catch (Exception e)
        {
            s_LOGGER.error ("调用药品冲抵退药入库异常:" + e.getLocalizedMessage (), e);
            throw new BusinessException ("调用药品冲抵退药入库异常:" + e.getLocalizedMessage (), e);
        }
    }

    /** 提交路径. */
    public static final String SCC_BRANCH = "$URL$";

    /** 提交日期. */
    public static final String SCC_LAST_MODIFICATION_DATE = "$Date$";

    /** 最终修改人员. */
    public static final String SCC_LAST_MODIFIER_NAME = "$Author$";

    /** 最终版本号. */
    public static final String SCC_REVISION = "$Revision$";

}
